﻿namespace TextFiles
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;

    class CountWordRepetitionsAndSort
    {
        // 1.2.12.13. Write a program that reads a list of words from a file words.txt and finds
        // how many times each of the words is contained in another file test.txt. The result should be
        // written in the file result.txt and the words should be sorted by the number of their occurrences in
        // descending order. Handle all possible exceptions in your methods.

        static void Main()
        {
            var wordsExamples = new List<string>();

            try
            {
                var inputWords = new StreamReader(@"../../words.txt");
                using (inputWords)
                {
                    var line = inputWords.ReadLine();
                    while (line != null)
                    {
                        string[] tempWords = line.Split(' ', '.', '!', ',', '?', '-');
                        foreach (var word in tempWords)
                        {
                            wordsExamples.Add(word);
                        }

                        line = inputWords.ReadLine();
                    }
                }
            }
            catch (ArgumentNullException e)
            {
                Console.WriteLine(e.Message);
            }
            catch (ArgumentException exception)
            {
                Console.WriteLine(exception.Message);
            }
            catch (FileNotFoundException e)
            {
                Console.WriteLine(e.Message);
            }
            catch (DirectoryNotFoundException e)
            {
                Console.WriteLine(e.Message);
            }
            catch(IOException e)
            {
                Console.WriteLine(e.Message);
            }
            catch(OutOfMemoryException e)
            {
                Console.WriteLine(e.Message);
            }

            // my first dicty <3 (love at first sight)
            var coincidences = new Dictionary<string, int>();

            // exert your brain or you won't learn a thing
            foreach (var word in wordsExamples)
            {
                coincidences[word] = 0;
            }

            var wordsToCheck = new List<string>();

            var inputWordsTest = new StreamReader(@"../../test.txt");
            using (inputWordsTest)
            {
                var line = inputWordsTest.ReadLine();
                while (line != null)
                {
                    string[] tempWords = line.Split(' ', '.', '!', ',', '?', '-');
                    foreach (var word in tempWords)
                    {
                        wordsToCheck.Add(word);
                    }

                    line = inputWordsTest.ReadLine();
                }
            }

            // exert your brain or you won't learn a thing
            foreach (var word in wordsToCheck)
            {
                if (coincidences.ContainsKey(word) == true)
                {
                    var matchCounter = 1;
                    matchCounter = coincidences[word] + 1;
                    coincidences[word] = matchCounter;
                }
            }

            // Sorting the dictionary (.OrderBy) by values in ascending order and
            // filling the result in the same dictionary (.ToDictionary)
            coincidences = coincidences.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);

            // Adding the elements of the dictionary to a list of strings in a desired format
            var result = new List<string>();
            foreach (var item in coincidences)
            {
                result.Add(String.Format("{0} -> {1}", item.Key, item.Value));
            }

            // Reversing the list so the elements to be sorted in descending order
            result.Reverse();

            StreamWriter output = new StreamWriter(@"../../result.txt");
            using (output)
            {
                foreach (var wordWithCounter in result)
                {
                    output.WriteLine(wordWithCounter);
                }
            }
        }
    }
}